#include "ST7305_UI.h"
#include "st7305_1p54_driver.h"
#include "esp_err.h"
#include <string.h>

#define ABS_DIFF(x, y) (((x) > (y))? ((x) - (y)) : ((y) - (x)))


ST7305_UI::ST7305_UI(uint16_t w, uint16_t h, uint8_t rotation)
{
    WIDTH = w;
    HEIGHT = h;
    Rotation = rotation;
}

ST7305_UI::~ST7305_UI() {
}

void ST7305_UI::writePoint(uint16_t x, uint16_t y, bool enabled){
}

void ST7305_UI::writePoint(uint16_t x, uint16_t y, uint8_t color) {
}

void ST7305_UI::drawPixel(uint16_t x, uint16_t y, bool enabled) {
    if ((x < WIDTH) && (y < HEIGHT)) {
    // Pixel is in-bounds. Rotate coordinates if needed.
        switch (Rotation) {
            case 1:
                value_interchange(x, y);
                x = WIDTH - x - 1;
                break;
            case 2:
                x = WIDTH - x - 1;
                y = HEIGHT - y - 1;
                break;
            case 3:
                value_interchange(x, y);
                y = HEIGHT - y - 1;
                break;
            default:
                break;
        }
        writePoint(x, y, enabled);
    }
}

void ST7305_UI::drawPixel(uint16_t x, uint16_t y, uint8_t color) {
    if ((x < WIDTH) && (y < HEIGHT)) {
    // Pixel is in-bounds. Rotate coordinates if needed.
        switch (Rotation) {
            case 1:
                value_interchange(x, y);
                x = WIDTH - x - 1;
                break;
            case 2:
                x = WIDTH - x - 1;
                y = HEIGHT - y - 1;
                break;
            case 3:
                value_interchange(x, y);
                y = HEIGHT - y - 1;
                break;
            default:
                break;
        }
        writePoint(x, y, color);
    }
}

void ST7305_UI::drawFastHLine(uint16_t x, uint16_t y, uint16_t len, uint8_t color) {
    // 这里是绘制水平线段的逻辑实现
    // 可以根据具体的图形绘制需求进行实现，例如循环绘制一系列像素点来组成水平线段
    bool bSwap = false;
    switch (Rotation) {
    case 1:
        // 90 degree rotation, swap x & y for rotation, then invert x
        bSwap = true;
        value_interchange(x, y);
        x = WIDTH - x - 1;
        break;
    case 2:
        // 180 degree rotation, invert x and y, then shift y around for height.
        x = WIDTH - x - 1;
        y = HEIGHT - y - 1;
        x -= (len - 1);
        break;
    case 3:
        // 270 degree rotation, swap x & y for rotation,
        // then invert y and adjust y for w (not to become h)
        bSwap = true;
        value_interchange(x, y);
        y = HEIGHT - y - 1;
        y -= (len - 1);
        break;
    }

    if (bSwap){
        for (uint16_t i = y; i < y + len; i++) {
            // 设置坐标 (x, i) 的像素颜色为 color
            // 根据你的实际图形绘制方式进行设置
            writePoint(x, i, color);
        }
    }
    else{
        for (uint16_t i = x; i < x + len; i++) {
            // 设置坐标 (i, y) 的像素颜色为 color
            // 根据你的实际图形绘制方式进行设置
            writePoint(i, y, color);
        }
    }
}

void ST7305_UI::drawLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color) {
    int16_t dx = ABS_DIFF(x2, x1);
    int16_t dy = ABS_DIFF(y2, y1);
    int16_t sx = (x1 < x2)? 1 : -1;
    int16_t sy = (y1 < y2)? 1 : -1;
    int16_t err = dx - dy;

    while (true) {
        drawPixel(x1, y1, color);
        if (x1 == x2 && y1 == y2) break;
        int16_t e2 = 2 * err;
        if (e2 > -dy) {
            err -= dy;
            x1 += sx;
        }
        if (e2 < dx) {
            err += dx;
            y1 += sy;
        }
    }
}

void ST7305_UI::drawFastVLine(uint16_t x, uint16_t y, uint16_t len, uint8_t color) {
    // 这里是绘制垂直线段的逻辑实现
    // 可以根据具体的图形绘制需求进行实现，例如循环绘制一系列像素点来组成垂直线段
    bool bSwap = false;
    switch (Rotation) {
    case 1:
        // 90 degree rotation, swap x & y for rotation,
        // then invert x and adjust x for h (now to become w)
        bSwap = true;
        value_interchange(x, y);
        x = WIDTH - x - 1;
        x -= (len - 1);
        break;
    case 2:
        // 180 degree rotation, invert x and y, then shift y around for height.
        x = WIDTH - x - 1;
        y = HEIGHT - y - 1;
        y -= (len - 1);
        break;
    case 3:
        // 270 degree rotation, swap x & y for rotation, then invert y
        bSwap = true;
        value_interchange(x, y);
        y = HEIGHT - y - 1;
        break;
    }

    if (bSwap){
        for (uint16_t i = x; i < x + len; i++) {
            // 设置坐标 (i, y) 的像素颜色为 color
            // 根据你的实际图形绘制方式进行设置
            writePoint(i, y, color);
        }
    }
    else{
        for (uint16_t i = y; i < y + len; i++) {
            // 设置坐标 (x, i) 的像素颜色为 color
            // 根据你的实际图形绘制方式进行设置
            writePoint(x, i, color);
        }
    }
}

void ST7305_UI::drawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint8_t color) {
    drawLine(x1, y1, x2, y2, color);
    drawLine(x2, y2, x3, y3, color);
    drawLine(x3, y3, x1, y1, color);
}

void ST7305_UI::drawFilledTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t color) {
    uint16_t polygonPoints[] = {x0, y0, x1, y1, x2, y2};
    drawFilledPolygon(polygonPoints, 3, color);
}

void ST7305_UI::drawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t color) {
    drawLine(x1, y1, x2, y1, color);
    drawLine(x2, y1, x2, y2, color);
    drawLine(x2, y2, x1, y2, color);
    drawLine(x1, y2, x1, y1, color);
}

void ST7305_UI::drawFilledRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t color) {
    for (uint16_t y = y1; y <= y2; y++) {
        for (uint16_t x = x1; x <= x2; x++) {
            drawPixel(x, y, color);
        }
    }
}

void ST7305_UI::drawCircle(uint16_t xc, uint16_t yc, uint16_t r, uint8_t  color) {
    int16_t x = 0;
    int16_t y = r;
    int16_t d = 3 - 2 * r;
    while (x <= y) {
        drawPixel(xc + x, yc + y, color);
        drawPixel(xc - x, yc + y, color);
        drawPixel(xc + x, yc - y, color);
        drawPixel(xc - x, yc - y, color);
        drawPixel(xc + y, yc + x, color);
        drawPixel(xc - y, yc + x, color);
        drawPixel(xc + y, yc - x, color);
        drawPixel(xc - y, yc - x, color);
        if (d < 0) {
            d = d + 4 * x + 6;
        } else {
            d = d + 4 * (x - y) + 10;
            y--;
        }
        x++;
    }
}

void ST7305_UI::drawFilledCircle(uint16_t centerX, uint16_t centerY, uint16_t radius, uint8_t  color) {
    uint16_t x = radius;
    uint16_t y = 0;
    uint16_t decisionOver2 = 1 - x;

    while (x >= y) {
        // 绘制水平线段填充圆形的八分之一
        for (uint16_t i = centerX - x; i <= centerX + x; i++) {
            drawPixel(i, centerY + y, color);
            drawPixel(i, centerY - y, color);
        }
        for (uint16_t i = centerX - y; i <= centerX + y; i++) {
            drawPixel(i, centerY + x, color);
            drawPixel(i, centerY - x, color);
        }

        y++;
        if (decisionOver2 <= 0) {
            decisionOver2 += 2 * y + 1;
        } else {
            x--;
            decisionOver2 += 2 * (y - x) + 1;
        }
    }
}

void ST7305_UI::drawPolygon(uint16_t* points, uint16_t n, uint8_t  color) {
    for (uint16_t i = 0; i < n; i++) {
        uint16_t j = (i + 1) % n;
        drawLine(points[2 * i], points[2 * i + 1], points[2 * j], points[2 * j + 1], color);
    }
}

void ST7305_UI::drawFilledPolygon(uint16_t* points, uint16_t n, uint8_t  color) {
    // 找到多边形的最小和最大 y 值
    uint16_t minY = points[1];
    uint16_t maxY = points[1];
    for (int16_t i = 0; i < n; ++i) {
        uint16_t y = points[2 * i + 1];
        if (y < minY) minY = y;
        if (y > maxY) maxY = y;
    }

    uint16_t* intersections = new uint16_t[2 * n];
    uint16_t intersectionCount = 0;

    for (uint16_t y = minY; y <= maxY; ++y) {
        intersectionCount = 0;
        for (uint16_t i = 0; i < n; ++i) {
            uint16_t nextIndex = (i + 1) % n;
            uint16_t x1 = points[2 * i];
            uint16_t y1 = points[2 * i + 1];
            uint16_t x2 = points[2 * nextIndex];
            uint16_t y2 = points[2 * nextIndex + 1];
            if ((y1 <= y && y2 > y) || (y2 <= y && y1 > y)) {
                uint16_t x = x1 + (y - y1) * (x2 - x1) / (y2 - y1);
                intersections[intersectionCount++] = x;
            }
        }

        // 排序交点
        for (uint16_t i = 0; i < intersectionCount - 1; ++i) {
            for (uint16_t j = i + 1; j < intersectionCount; ++j) {
                if (intersections[i] > intersections[j]) {
                    uint16_t temp = intersections[i];
                    intersections[i] = intersections[j];
                    intersections[j] = temp;
                }
            }
        }

        for (uint16_t i = 0; i < intersectionCount; i += 2) {
            uint16_t startX = intersections[i];
            uint16_t endX = intersections[i + 1];
            for (uint16_t x = startX; x < endX; ++x) {
                drawPixel(x, y, color);
            }
        }
    }

    delete[] intersections;
}

void ST7305_UI::setRotation(uint8_t r){
    Rotation = r;
}

void ST7305_UI::drawXBM(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t* xbmData) {
    uint16_t bytesPerRow = (width + 7) / 8; // 计算每行需要多少个字节
    for (uint16_t row = 0; row < height; ++row) {
        for (uint16_t byteIndex = 0; byteIndex < bytesPerRow; ++byteIndex) {
            uint8_t byte = xbmData[row * bytesPerRow + byteIndex];
            for (uint8_t bit = 0; bit < 8; ++bit) {
                uint16_t col = byteIndex * 8 + bit;
                if (col < width) { // 确保列索引在有效范围内
                    bool pixel = (byte & (1 << (7 - bit))) != 0;
                    drawPixel(x + col, y + row, pixel);
                }
            }
        }
    }
}